| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- <template>
- <div>
- <div class="admin--page-content">
- <div class="admin--form">
- <!-- 낚시지역 상세 -->
- <table class="admin--form--table">
- <colgroup>
- <col style="width: 120px;">
- <col>
- </colgroup>
- <tbody>
- <tr>
- <th><div>지역명</div></th>
- <td>{{ formData.name || "-" }}</td>
- </tr>
- <tr>
- <th><div>등록일</div></th>
- <td>{{ formatDateTime(formData.created_at) }}</td>
- </tr>
- <tr>
- <th><div>최근 수정</div></th>
- <td>{{ formatDateTime(formData.updated_at) }}</td>
- </tr>
- </tbody>
- </table>
-
- <!-- 버튼 영역 -->
- <div class="admin--form-actions">
- <button type="button" class="admin--btn" @click="goToList">
- ← 목록으로
- </button>
- <button type="button" class="admin--btn admin--btn-red-border ml--auto" @click="handleDelete">
- 삭제
- </button>
- <button type="button" class="admin--btn admin--btn-red" @click="goToEdit">
- 수정
- </button>
- </div>
-
- <!-- 알림 모달 -->
- <AdminAlertModal
- v-if="alertModal.show"
- :title="alertModal.title"
- :message="alertModal.message"
- :type="alertModal.type"
- @confirm="handleAlertConfirm"
- @cancel="handleAlertCancel"
- @close="closeAlertModal"
- />
- </div>
- </div>
- <div class="admin--page-content mt--20">
- <div class="admin--sub--table--title">
- <p>해당 지역의 낚시어선 / 낚시터</p>
- <div class="sub--table--info">
- <span>🎣 낚시터 {{ fishingCount }}</span>
- <span>🚢 낚시어선 {{ onboardCount }}</span>
- </div>
- </div>
- <!-- 해당 지역의 어선 / 낚시터 -->
- <div class="admin--table-wrapper">
- <table class="admin--table">
- <thead>
- <tr>
- <th style="width: 80px;">번호</th>
- <th style="width: 180px;">구분</th>
- <th>이름</th>
- <th>주소</th>
- <th>상태</th>
- <th style="width: 120px;">등록일</th>
- </tr>
- </thead>
- <tbody>
- <tr v-if="isPlacesLoading">
- <td colspan="6" class="admin--table-loading">데이터를 불러오는 중...</td>
- </tr>
- <tr v-else-if="!places || places.length === 0">
- <td colspan="6" class="admin--table-empty">해당 지역에 등록된 낚시어선/낚시터가 없습니다.</td>
- </tr>
- <tr
- v-else
- v-for="(p, index) in places"
- :key="p.place_type + '-' + p.id"
- class="admin--table-row-clickable"
- @click="goToPlace(p)"
- >
- <td class="date">{{ (onboardCount + fishingCount) - index }}</td>
- <td>
- <span :class="['admin--badge', p.place_type === 'onboard' ? 'admin--badge-active' : 'admin--badge-html']">
- {{ p.place_type === "onboard" ? "낚시어선" : "낚시터" }}
- </span>
- </td>
- <td class="admin--table-title">{{ p.name }}</td>
- <td>{{ p.address || "-" }}</td>
- <td>
- <span :class="['admin--badge', p.status_YN === 'Y' ? 'admin--badge-active' : 'admin--badge-ended']">
- {{ p.status_YN === "Y" ? "사용중" : "미사용" }}
- </span>
- </td>
- <td class="date">{{ formatDate(p.created_at) }}</td>
- </tr>
- </tbody>
- </table>
- </div>
- <!-- 전체보기 버튼 -->
- <div class="admin--form" v-if="(onboardCount + fishingCount) > places.length">
- <div class="admin--form-actions">
- <button type="button" class="txt--btn ml--auto" @click="goToPlacesAll">
- {{ onboardCount + fishingCount }}건 전체보기 ->
- </button>
- </div>
- </div>
- </div>
- </div>
- </template>
- <script setup>
- import { ref, onMounted } from "vue";
- import { useRoute, useRouter } from "vue-router";
- import AdminAlertModal from "~/components/admin/AdminAlertModal.vue";
- definePageMeta({
- layout: "admin",
- middleware: ["auth"],
- });
- const route = useRoute();
- const router = useRouter();
- const { get, del } = useApi();
- const areaId = route.params.id;
- const formData = ref({
- name: "",
- created_at: "",
- updated_at: "",
- });
- // 해당 지역의 낚시어선 / 낚시터
- const places = ref([]);
- const onboardCount = ref(0);
- const fishingCount = ref(0);
- const isPlacesLoading = ref(false);
- // 알림 모달
- const alertModal = ref({
- show: false,
- title: "알림",
- message: "",
- type: "alert",
- onConfirm: null,
- });
- const showAlert = (message, title = "알림") => {
- alertModal.value = { show: true, title, message, type: "alert", onConfirm: null };
- };
- const showConfirm = (message, onConfirm, title = "확인") => {
- alertModal.value = { show: true, title, message, type: "confirm", onConfirm };
- };
- const closeAlertModal = () => { alertModal.value.show = false; };
- const handleAlertConfirm = () => {
- if (alertModal.value.onConfirm) alertModal.value.onConfirm();
- closeAlertModal();
- };
- const handleAlertCancel = () => closeAlertModal();
- // 상세 조회
- const loadDetail = async () => {
- const { data, error } = await get(`/area/${areaId}`);
- if (error || !data?.success) {
- showAlert(error?.message || data?.message || "조회에 실패했습니다.", "오류");
- return;
- }
- const row = data.data || {};
- formData.value = {
- name: row.name ?? "",
- created_at: row.created_at ?? "",
- updated_at: row.updated_at ?? "",
- };
- };
- // 삭제
- const handleDelete = () => {
- // 연결된 데이터 있으면 차단
- const total = onboardCount.value + fishingCount.value;
- if (total > 0) {
- showAlert(
- `해당 지역에 등록된 낚시어선/낚시터가 있어 삭제할 수 없습니다.\n(낚시어선 ${onboardCount.value} / 낚시터 ${fishingCount.value})\n\n먼저 연결된 어선/낚시터를 다른 지역으로 옮기거나 삭제해 주세요.`,
- "삭제 불가"
- );
- return;
- }
- showConfirm(
- `'${formData.value.name}' 낚시지역을 삭제하시겠습니까?`,
- async () => {
- const { data, error } = await del(`/area/${areaId}`);
- if (error || !data?.success) {
- showAlert(error?.message || data?.message || "삭제에 실패했습니다.", "오류");
- } else {
- showAlert(data.message || "삭제되었습니다.", "성공");
- setTimeout(() => router.push("/site-manager/area/list"), 800);
- }
- },
- "낚시지역 삭제"
- );
- };
- // 이동
- const goToList = () => router.push("/site-manager/area/list");
- const goToEdit = () => router.push(`/site-manager/area/edit/${areaId}`);
- const goToPlace = (p) => {
- if (p.place_type === "onboard") {
- router.push(`/site-manager/onboard/detail/${p.id}`);
- } else if (p.place_type === "fishing") {
- router.push(`/site-manager/fishing/detail/${p.id}`);
- }
- };
- const goToPlacesAll = () => router.push(`/site-manager/area/places/${areaId}`);
- // 해당 지역의 낚시어선/낚시터 로드 (최근 등록순 8개 + 카운트)
- const loadPlaces = async () => {
- isPlacesLoading.value = true;
- const { data, error } = await get(`/area/${areaId}/places`, { params: { limit: 8 } });
- if (!error && data?.success && data?.data) {
- places.value = data.data.items || [];
- onboardCount.value = data.data.onboard_count || 0;
- fishingCount.value = data.data.fishing_count || 0;
- }
- isPlacesLoading.value = false;
- };
- // 일시 포맷
- const formatDateTime = (dateString) => {
- if (!dateString) return "-";
- const date = new Date(dateString.replace(" ", "T"));
- if (isNaN(date.getTime())) return dateString;
- return date.toLocaleString("ko-KR", {
- year: "numeric",
- month: "2-digit",
- day: "2-digit",
- hour: "2-digit",
- minute: "2-digit",
- });
- };
- // 날짜만
- const formatDate = (dateString) => {
- if (!dateString) return "-";
- const date = new Date(dateString.replace(" ", "T"));
- if (isNaN(date.getTime())) return dateString;
- return date.toLocaleDateString("ko-KR", { year: "numeric", month: "2-digit", day: "2-digit" });
- };
- onMounted(() => {
- loadDetail();
- loadPlaces();
- });
- </script>
|